package zz.app.yzjproject

import android.Manifest
import android.annotation.SuppressLint
import android.app.ProgressDialog
import android.app.Service
import android.bluetooth.*
import android.content.*
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Vibrator
import android.support.annotation.RequiresApi
import android.support.design.widget.BottomNavigationView
import android.support.v4.content.ContextCompat
import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatActivity
import android.text.Editable
import android.text.Html
import android.text.Spanned
import android.view.*
import android.widget.*
import kotlin.experimental.and

@RequiresApi(Build.VERSION_CODES.N)
class MainActivity : AppCompatActivity() {

    var funcFragment: FuncFragment? = null
    var debugFragment: DebugFragment? = null
    var graphicFragment: GraphicFragment? = null
    var bleState = 0
    var  mRssiThread:Thread?=null
    var mVibrator:Vibrator?=null
    lateinit var bleStateReceiver: BroadcastReceiver
    lateinit var macpartList: List<EditText>
    lateinit var mBluetoothAdapter: BluetoothAdapter
    lateinit var tvBluetoothState: TextView
    lateinit var tvBluetoothRssi: TextView
    lateinit var navigation:BottomNavigationView
    var mBluetoothGatt: BluetoothGatt?=null
    var mReadChar:BluetoothGattCharacteristic?=null
    var mWriteChar:BluetoothGattCharacteristic?=null
    var mWriteProgressDialog:ProgressDialog?=null
    var currentBluetoothDevice: BluetoothDevice?=null
    val mHandler=Handler(Handler.Callback { msg ->
        when(msg.what){
            HandlerMSG.MSG_SENDCOMMAND->{
                if(canComm()) {
                    mWriteChar?.value = msg.obj as ByteArray
                    mBluetoothGatt?.writeCharacteristic(mWriteChar)
                    if ((mWriteChar!=null)&&(mWriteChar!!.value[2] and (1 shl 7).toByte()) == 0.toByte()) {
                        mWriteProgressDialog = ProgressDialog(this@MainActivity)
                        mWriteProgressDialog?.setMessage("正在写入")
                        mWriteProgressDialog?.show()
                    }
                }
            }
        }
        true
    })
    private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
        when (item.itemId) {
            R.id.navigation_func -> {
                showFuncFragment()
                return@OnNavigationItemSelectedListener true
            }
            R.id.navigation_debug -> {
                showDebugFragment()
                return@OnNavigationItemSelectedListener true
            }
            R.id.navigation_graphic -> {
                showGraphicFragment()
                return@OnNavigationItemSelectedListener true
            }
        }
        false
    }
    private fun hideAllFragments() {
        if(!isDestroyed) {
            fragmentManager.beginTransaction().hide(funcFragment).commit()
            fragmentManager.beginTransaction().hide(debugFragment).commit()
            fragmentManager.beginTransaction().hide(graphicFragment).commit()
        }
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        bleStateReceiver = object : BroadcastReceiver() {
            override fun onReceive(context: Context?, intent: Intent) {
                if (intent.action == BluetoothAdapter.ACTION_STATE_CHANGED) {
                    if (BluetoothAdapter.STATE_OFF == intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0)) {
                        bleState = 0
                        funcFragment?.mListView?.isEnabled=false
                        showFuncFragment()
                        mReadChar=null
                        mWriteChar=null
                        if(mRssiThread!=null&&mRssiThread!!.isAlive){
                            mRssiThread!!.interrupt()
                            mRssiThread=null
                        }
                    }
                    if (BluetoothAdapter.STATE_ON == intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0)) {
                        temptOpenBLE()

                    }
                }
                CheckBluetoothState()
            }
        }
        registerReceiver(bleStateReceiver, IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED))
        navigation = findViewById(R.id.navigation)
        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
        tvBluetoothState = findViewById(R.id.tvBluetoothState)
        tvBluetoothRssi = findViewById(R.id.tvBluetoothRSSI)
        funcFragment = FuncFragment()
        debugFragment = DebugFragment()
        graphicFragment= GraphicFragment()
        fragmentManager.beginTransaction().add(R.id.content, funcFragment).commit()
        fragmentManager.beginTransaction().add(R.id.content, debugFragment).commit()
        fragmentManager.beginTransaction().add(R.id.content, graphicFragment).commit()
        showFuncFragment()
        if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(this@MainActivity, Manifest.permission.ACCESS_COARSE_LOCATION)) {
            requestPermissions(arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION), 1)
        }
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
        if(!mBluetoothAdapter.isEnabled)
        mBluetoothAdapter.enable()
        else{
            temptOpenBLE()
        }
        mVibrator=getSystemService(Service.VIBRATOR_SERVICE) as Vibrator

        CheckBluetoothState()

    }

    private fun showFuncFragment() {
        hideAllFragments()
        fragmentManager.beginTransaction().show(funcFragment).commit()
    }
    private fun showDebugFragment() {
        hideAllFragments()
        fragmentManager.beginTransaction().show(debugFragment).commit()
    }
    private fun showGraphicFragment() {
        hideAllFragments()
        fragmentManager.beginTransaction().show(graphicFragment).commit()
    }
    override fun onDestroy() {
        super.onDestroy()
        unregisterReceiver(bleStateReceiver)
    }

    override fun onStop() {
        super.onStop()

    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        var d:AlertDialog?=null
        when (item.itemId) {
            R.id.menuSetting-> {
                val view = View.inflate(this, R.layout.maclist_layout, null)

                d = AlertDialog.Builder(this)
                        .setTitle("请选择蓝牙："
                        ).setPositiveButton("添加") { _, _ ->

                    var bFirst = false
                    val settingView = View.inflate(this, R.layout.setting_layout, null)
                    macpartList = listOf(
                            settingView.findViewById(R.id.macpart1)  ,
                            settingView.findViewById(R.id.macpart2)  ,
                            settingView.findViewById(R.id.macpart3)  ,
                            settingView.findViewById(R.id.macpart4)  ,
                            settingView.findViewById(R.id.macpart5)  ,
                            settingView.findViewById(R.id.macpart6)
                    )
                    for (part in macpartList) {
                        part.addTextChangedListener(object : MacTextWatcher(part) {
                            override fun afterTextChanged(s: Editable?) {
                                part.setSelection(part.text.length)
                            }

                            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {

                            }

                            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                                when (before) {
                                    0 -> {
                                        if (s.length > 0 && !s[start].isHex() || s.length > 2) {
                                            part.setText(s.subSequence(0, s.length - 1))
                                        }
                                        this.strFinal = part.text.toString().toUpperCase()
                                        if (!strFinal.equals(part.text.toString())) {
                                            part.setText(strFinal)
                                        }
                                        if (part.text.length == 2) {
                                            when (part) {
                                                macpartList[0] -> macpartList[1].requestFocus()
                                                macpartList[1] -> macpartList[2].requestFocus()
                                                macpartList[2] -> macpartList[3].requestFocus()
                                                macpartList[3] -> macpartList[4].requestFocus()
                                                macpartList[4] -> macpartList[5].requestFocus()
                                            }
                                        }

                                    }
                                }
                            }
                        })
                        part.setOnFocusChangeListener { v, hasFocus ->
                            if (bFirst) bFirst = false
                            else if (hasFocus) (v as EditText).text = null

                        }
                        part.setOnClickListener { v -> (v as EditText).text = null }
                    }

                    val d2 = AlertDialog.Builder(this)
                            .setTitle("请输入MAC：").setPositiveButton("确定") { _, _ ->
                        var bOK = true
                        for (i in 0..5) {
                            if (macpartList[i].text.length != 2) {
                                bOK = false
                                break
                            } else {
                                if (!(macpartList[i].text[0].isHex() && macpartList[i].text[0].isHex())) {
                                    bOK = false
                                    break
                                }
                            }
                        }
                        when (bOK) {
                            true -> {
                                val builder = StringBuilder()
                                for (i in 0 until 5) {
                                    builder.append(macpartList[i].text)
                                    builder.append('-')
                                }
                                builder.append(macpartList[5].text)
                                val temp = getSharedPreferences("BLEMAC", Context.MODE_PRIVATE).getString("value", null)
                                var temp2 = ""
                                if (temp != null) {
                                    val temp3 = temp.split(' ')
                                    for (t in temp3) {
                                        temp2 += t
                                        if(!t.equals(""))
                                        temp2 += " "
                                    }

                                }
                                temp2 += builder.toString()
                                getSharedPreferences("BLEMAC", Context.MODE_PRIVATE).edit().putString("value", temp2).apply()
                                Toast.makeText(this@MainActivity, "BLEMAC添加成功", Toast.LENGTH_SHORT).show()


                            }
                            false -> {
                                Toast.makeText(this@MainActivity, "由于一些地址段不正确，BLEMAC添加失败", Toast.LENGTH_SHORT).show()
                            }
                        }
                        d?.show()
                    }.setView(settingView).show()
                    d2.show()

                }.setView(view).create()
                d?.setOnShowListener {
                    var macs = getSharedPreferences("BLEMAC", Context.MODE_PRIVATE).getString("value", null)
                    var macs2: List<String>? = null
                    val list = view.findViewById<ListView>(R.id.macs)
                    if (!macs.isNullOrEmpty()) {
                        macs2 = macs.split(' ')
                        list.adapter = ArrayAdapter<String>(this, R.layout.listview_layout, macs2)
                    } else list.adapter = null
                    list.setOnItemClickListener { _, _, position, _ ->
                        val str = list.adapter.getItem(position) as String
                        getSharedPreferences("BLEMACCurrent", Context.MODE_PRIVATE).edit().putString("value", str).apply()
                        if(mBluetoothGatt!=null){
                            mBluetoothGatt!!.disconnect()
                            mBluetoothGatt!!.close()
                            mBluetoothGatt=null
                        }
                        bleState=0
                        CheckBluetoothState()
                        Toast.makeText(this,"设置成功",Toast.LENGTH_SHORT).show()
                        d?.dismiss()
                    }

                    list.setOnItemLongClickListener { _, view, _, _ ->
                        val menu = PopupMenu(this, view)
                        menu.menu.add("删除")
                        menu.setOnMenuItemClickListener {
                            val tv = view as TextView
                            val strtv = tv.text
                            val s = StringBuilder()
                            if (macs2!!.size != 0) {
                                for (i in macs2!!) {
                                    if (!i.equals(strtv)) {
                                        s.append(i + " ")
                                    }
                                }
                            }

                            val str = s.substring(0, if (s.length > 0) s.length - 1 else 0)
                            getSharedPreferences("BLEMAC", Context.MODE_PRIVATE).edit().putString("value", str).apply()
                            macs = getSharedPreferences("BLEMAC", Context.MODE_PRIVATE).getString("value", null)
                            if (!macs.isNullOrEmpty()) {
                                macs2 = macs.split(' ')
                                list.adapter = ArrayAdapter<String>(this, R.layout.listview_layout, macs2)
                            } else
                                list.adapter = null

                            true
                        }
                        menu.show()
                        true
                    }
                }

                d?.show()
            }
            R.id.menuConnect -> {
                temptOpenBLE()
                funcFragment?.tvSend?.text=null
                funcFragment?.tvReceive?.text=null
                funcFragment?.readCnt=0
                funcFragment?.writeCnt=0
            }

        }
        return true
    }




    fun temptOpenBLE(){
        val sharedPref = getSharedPreferences("BLEMACCurrent", Context.MODE_PRIVATE)
        val bleMac = sharedPref.getString("value", null)
        if (bleMac != null&&bleMac.length>0) {
            if (mBluetoothAdapter.isEnabled) {
                val bluetoothDevice: BluetoothDevice? = mBluetoothAdapter.getRemoteDevice(bleMac.replace('-', ':'))
                if (bluetoothDevice != null) {
                    if (bleState == 0) {
                        mBluetoothGatt = bluetoothDevice.connectGatt(this@MainActivity, false, gattCallBack)
                        Toast.makeText(this@MainActivity,"正在连接",Toast.LENGTH_SHORT).show()
                    }
                }
                else {
                    Toast.makeText(this@MainActivity, "蓝牙设备无效", Toast.LENGTH_SHORT).show()
                }
            } else {
                Toast.makeText(this@MainActivity, "请打开蓝牙", Toast.LENGTH_SHORT).show()
            }


        } else {
            Toast.makeText(this@MainActivity, "未设置BLEMAC，无法建立连接", Toast.LENGTH_SHORT).show()
        }

    }
    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.mainmenu, menu)
        return true
    }
    val gattCallBack=object:BluetoothGattCallback() {
        override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
            super.onConnectionStateChange(gatt, status, newState)
            if (status == BluetoothGatt.GATT_SUCCESS) {
                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    mHandler.post {
                        bleState = 1
                        CheckBluetoothState()
                        gatt!!.discoverServices()

                    }
                    mRssiThread = Thread(object : Runnable {
                        override fun run() {
                            try {
                                while (!Thread.interrupted()) {
                                    mBluetoothGatt?.readRemoteRssi()
                                    Thread.sleep(500)
                                }
                                mHandler.post { tvBluetoothRssi.text = getString(R.string.strrssi) }
                            }catch(ex:InterruptedException){

                            }
                        }
                    })
                    mRssiThread?.start()

                }
            } else if(status==22) {
                if(newState==0){
                    mHandler.post {
                        bleState=0
                        tvBluetoothRssi.text = getString(R.string.strrssi)
                        Toast.makeText(this@MainActivity, "配对密码错误，连接中断", Toast.LENGTH_SHORT).show()
                        CheckBluetoothState()
                        funcFragment?.mListView?.isEnabled=false
                        if(mWriteProgressDialog!=null&&mWriteProgressDialog!!.isShowing)
                            mWriteProgressDialog!!.dismiss()

                    }
                }

            } else if(newState == BluetoothProfile.STATE_DISCONNECTED){
                mHandler.post {
                    bleState=0
                    tvBluetoothRssi.text = getString(R.string.strrssi)
                    Toast.makeText(this@MainActivity, "连接失败", Toast.LENGTH_SHORT).show()
                    CheckBluetoothState()
                    funcFragment?.mListView?.isEnabled=false

                }


            }
        }
        override fun onReadRemoteRssi(gatt: BluetoothGatt?, rssi: Int, status: Int) {
            super.onReadRemoteRssi(gatt, rssi, status)
            if(status==BluetoothGatt.GATT_SUCCESS){
                mHandler.post { tvBluetoothRssi.text=rssi.toString() }
            }

        }
        override fun onCharacteristicWrite(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int) {
            super.onCharacteristicWrite(gatt, characteristic, status)
            if(characteristic==mWriteChar){
                if(status==BluetoothGatt.GATT_SUCCESS) {
                    mHandler.post {
                        mWriteProgressDialog?.dismiss()
                        if((characteristic!!.value[2] and (1 shl 7).toByte())==0.toByte())
                        Toast.makeText(this@MainActivity,"写入成功",Toast.LENGTH_SHORT).show()
                    }
                }else{
                    mHandler.post {
                        mWriteProgressDialog?.dismiss()
                        if((characteristic!!.value[2] and (1 shl 7).toByte())==0.toByte())
                        Toast.makeText(this@MainActivity,"写入失败:${status}",Toast.LENGTH_SHORT).show()
                    }
                }

            }
        }
        override fun onCharacteristicRead(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int) {
            super.onCharacteristicRead(gatt, characteristic, status)
        }

        override fun onCharacteristicChanged(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic) {
            super.onCharacteristicChanged(gatt, characteristic)
            if(characteristic==mReadChar) {
                mHandler.post {Procedure(mReadChar?.value)
                }
            }
        }
        override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
            super.onServicesDiscovered(gatt, status)
            if(status==BluetoothGatt.GATT_SUCCESS) {
                val beaconService = gatt!!.getService(Utils.beaconServiceUUID)
                mWriteChar = beaconService.getCharacteristic(Utils.writeCharUUID)
                mReadChar = beaconService.getCharacteristic(Utils.readCharUUID)
                val isEnableNotification = gatt.setCharacteristicNotification(mReadChar, true)
                if (isEnableNotification) {
                    val descriptorList = mReadChar?.descriptors
                    if (descriptorList != null && descriptorList.size > 0) {
                        for (descriptor in descriptorList) {
                            descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
                            gatt.writeDescriptor(descriptor)
                        }
                    }

                }
                mHandler.post {
                    Toast.makeText(this@MainActivity, "连接成功", Toast.LENGTH_SHORT).show()
                    bleState = 2
                    debugFragment?.linechartview?.mDegreeData?.clear()
                    funcFragment?.mListView?.isEnabled = true
                    CheckBluetoothState()
                }
            }else{
                Toast.makeText(this@MainActivity, "获取服务失败", Toast.LENGTH_SHORT).show()
                bleState = 0
                funcFragment?.mListView?.isEnabled = false
                CheckBluetoothState()
            }
        }
    }

    @SuppressLint("SetTextI18n")
    fun Procedure(value:ByteArray?) {
        if(value!=null)
        if(value[0]==0xAA.toByte()){
            if(value[1]==0x00.toByte()||value[1]==0x01.toByte()){
                if(value[2]==0x55.toByte()){
                    val temp=ByteArray(3,{value[it]})
                    var str=temp.joinToString(prefix = "[",postfix = "]"){it.toHex()}
                    when(value[1]){
                        0x00.toByte()->{
                            str+="\n->设置失败"

                        }
                        0x01.toByte()->{
                            str+="\n->设置成功"
                        }

                    }
                    funcFragment?.receiveDebug(str)
                }
            }
            else {
                val len = value[1]
                if (len < 19 && value[len + 1] == 0x55.toByte()) {
                    when (value[2].toInt()) {
                        //Start with 3
                        CustomCommand.UTCTIME -> {
                            //UTC TIME BACK
                            val (year, month, day, hour, minute, second)
                                    = Utils.convertUTCTimeSecondToDateTime((value[3].ConvertToInt() + value[4].ConvertToInt() * 256 + value[5].ConvertToInt() * 65536 + value[6].ConvertToInt() * 16777216))
                            debugFragment?.tvTime?.text = "${year}年${month}月${day}日${hour}时${minute}分${second}秒"
                        }
                        CustomCommand.MPU6050 -> {
                            //MPU6050 BACK
                            val (ax,ay,az,temp,gx,gy,gz)
                                    =Utils.distributeMPU6050Data(ByteArray(14,{value[it+3]}))
                            debugFragment?.tvMPU6050ax?.text="accelx:$ax"
                            debugFragment?.tvMPU6050ay?.text="accely:$ay"
                            debugFragment?.tvMPU6050az?.text="accelz:$az"
                            debugFragment?.tvMPU6050gx?.text="gyrox :$gx"
                            debugFragment?.tvMPU6050gy?.text="gyroy :$gy"
                            debugFragment?.tvMPU6050gz?.text="gyroz :$gz"
                            debugFragment?.tvMPU6050temp?.text="temp:$temp-->real:${String.format("%.2f",temp.toTemperature())}°C"

                        }
                        CustomCommand.DEGREE->{
                            val data
                                    =Utils.distributeDegreeData(ByteArray(8,{value[it+3]}))
                            debugFragment?.tvDegreeOrig?.text= String.format("%.2f",data.ori)+"°"
                            debugFragment?.tvDegreeKalman?.text=String.format("%.2f",data.kal)+"°"
                            if(debugFragment!=null&&debugFragment!!.linechartview!=null){
                                if(!debugFragment!!.linechartview!!.mDegreeData.offer(data)){
                                    debugFragment!!.linechartview!!.mDegreeData.poll()
                                    debugFragment!!.linechartview!!.mDegreeData.add(data)
                                }
                                debugFragment!!.linechartview!!.invalidate()
                            }

                        }
                    }

                }

            }
        }
    }


    @RequiresApi(Build.VERSION_CODES.N)
    fun CheckBluetoothState() {
        with(tvBluetoothState) {
            val str = "设备状态:%s BLE状态:%s"
            var res: Spanned?=null
            if (mBluetoothAdapter.isEnabled) {
                when (bleState) {
                    0 -> res = Html.fromHtml(String.format(str, "<font color=green>已开启</font>", "<font color=#ff0000>未连接</font>"), Html.FROM_HTML_MODE_LEGACY)
                    1 -> res = Html.fromHtml(String.format(str, "<font color=green>已开启</font>", "<font color=#00ffff>已连接</font>"), Html.FROM_HTML_MODE_LEGACY)
                    2 -> res = Html.fromHtml(String.format(str, "<font color=green>已开启</font>", "<font color=#00ff00>可通信</font>"), Html.FROM_HTML_MODE_LEGACY)
                }
            }else {
                res = Html.fromHtml(String.format(str, "<font color=red>未开启</font>", "<font color=red>未连接</font>"), Html.FROM_HTML_MODE_LEGACY)

            }
            text = res?: str

        }
        val str=getSharedPreferences("BLEMACCurrent", Context.MODE_PRIVATE).getString("value","无");
        val str2=str.replace('-',':')
        title="BLE："+str2
    }
    fun canComm()=bleState==2

}

private fun Int.toTemperature(): Double = (this +13200)/280.toDouble()-13

fun Char.isHex(): Boolean = this in '0'..'9' || this in 'a'..'f' || this in 'A'..'F'
fun Int.isLeapYear(): Boolean {
    if (this and 3 != 0) {
        return false
    }
    return this % 100 != 0 || this % 400 == 0
}
fun Byte.ConvertToInt()=if(this<0) 256+this else this.toInt()
data class DateTimeData(val year:Int, val month:Int, val day:Int, val hour:Int, val minute:Int, val second:Int)
data class MPU6050Data(val ax:Int,val ay:Int,val az:Int,val temp:Int,val gx:Int,val gy:Int,val gz:Int)
data class DegreeData(val ori:Float,val kal:Float)
object CustomCommand{
    val UTCTIME=0x11
    val MPU6050=0x12
    val DEGREE=0x13

}